package v1

import (
	"encoding/json"
	"errors"
	"sweetsunnyflower/app/models/address"
	"sweetsunnyflower/app/models/chat"
	"sweetsunnyflower/app/models/trip_passenger"
	"sweetsunnyflower/app/models/user_car"
	"sweetsunnyflower/app/models/user_follow"
	"sweetsunnyflower/app/models/user_trip"
	"sweetsunnyflower/app/policies"
	"sweetsunnyflower/app/queues"
	"sweetsunnyflower/app/requests"
	"sweetsunnyflower/pkg/auth"
	"sweetsunnyflower/pkg/response"
	"sweetsunnyflower/pkg/websocket"

	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
)

type UserTripsController struct {
	Controller
}

func (ctrl *UserTripsController) Share(c *gin.Context) {
	userTripModel := user_trip.Get(c.Param("id"))
	if userTripModel.ID == 0 {
		response.Abort404(c)
		return
	}

	//		   id: 1,
	//         start: "大同市",
	//         end: "新荣区",
	//         time: "2021-12-31 15:46",
	//         remark: "华严寺到新荣区，车满发车",
	//         price: "10",

	content := chat.TripContent{
		ID:     userTripModel.ID,
		Start:  userTripModel.Start.Name,
		End:    userTripModel.End.Name,
		Time:   userTripModel.Time,
		Remark: userTripModel.Remark,
		Price:  userTripModel.Price,
	}

	con, err := json.Marshal(content)

	if err != nil {
		response.Abort500(c, "服务异常")
	}
	// 消息入库
	chatModel := &chat.Chat{
		UserID:  auth.CurrentIntUID(c),
		Type:    chat.ChatTypeTrip,
		Content: string(con),
		ToID:    userTripModel.UserID,
	}

	chatModel.Save()

	if chatModel.ID > 0 {
		// 广播内容
		websocket.NewClientManager().Broadcast(Format("replay", chat.GetByID(chatModel.ID)), websocket.TextMessage, nil)
	}

	response.Created(c, nil)
}

func (ctrl *UserTripsController) Index(c *gin.Context) {
	request := requests.UserTripsQueryRequest{}
	if ok := requests.Validate(c, &request, requests.UserTripsQuery); !ok {
		return
	}
	if request.Owner {
		request.UserID = auth.CurrentIntUID(c)
	}
	userTrips := user_trip.GetByLatestId(request)
	count := user_trip.Count(request)

	response.Data(c, gin.H{
		"trips": userTrips,
		"total": count,
	})
}

func (ctrl *UserTripsController) Show(c *gin.Context) {
	userTripModel := user_trip.Get(c.Param("id"))
	if userTripModel.ID == 0 {
		response.Abort404(c)
		return
	}

	userID := auth.CurrentIntUID(c)

	userTrip, err := user_trip.FormatTrip(userTripModel)

	if err != nil {
		response.Abort500(c, "服务异常")
	}

	// 查询是否关注
	follow, _, err := user_follow.IsFollow(userID, userTripModel.UserID)
	if err != nil {
		response.Abort500(c, "服务异常")
		return
	}
	userTrip.Follow = follow

	response.Data(c, userTrip)

}

func (ctrl *UserTripsController) Store(c *gin.Context) {

	request := requests.UserTripRequest{}
	if ok := requests.Validate(c, &request, requests.UserTripSave); !ok {
		return
	}

	// 车辆校验
	carModel := user_car.Get(cast.ToString(request.CarId))

	if carModel.ID == 0 {
		response.ValidationError(c, map[string][]string{
			"start_id": {"车辆不存在"},
		})
		return
	}

	// 始发地校验
	startModel := address.Get(cast.ToString(request.StartID))
	if startModel.ID == 0 {
		response.ValidationError(c, map[string][]string{
			"start_id": {"始发地不存在"},
		})
		return
	}

	// 目的地校验
	endModel := address.Get(cast.ToString(request.EndID))
	if endModel.ID == 0 {
		response.ValidationError(c, map[string][]string{
			"end_id": {"目的地不存在"},
		})
		return
	}
	// 是否有正在进行中的行程

	userTripModel := user_trip.UserTrip{
		UserID:    auth.CurrentIntUID(c),
		StartID:   request.StartID,
		EndID:     request.EndID,
		Time:      request.Time,
		CarId:     request.CarId,
		Sites:     request.Sites,
		Remaining: request.Sites,
		Price:     request.Price,
		Status:    1,
		Remark:    request.Remark,
	}
	userTripModel.Create()
	if userTripModel.ID > 0 {

		response.Created(c, userTripModel)

		queues.PublishEvent(userTripModel.ID)

	} else {
		response.Abort500(c, "创建失败，请稍后尝试~")
	}
}

func (ctrl *UserTripsController) Update(c *gin.Context) {

	userTripModel := user_trip.Get(c.Param("id"))
	if userTripModel.ID == 0 {
		response.Abort404(c)
		return
	}

	if ok := policies.CanModifyUserTrip(c, userTripModel); !ok {
		response.Abort403(c)
		return
	}

	request := requests.UserTripRequest{}
	if ok := requests.Validate(c, &request, requests.UserTripSave); !ok {
		return
	}

	// userTripModel.FieldName = request.FieldName
	rowsAffected := userTripModel.Save()
	if rowsAffected > 0 {
		response.Data(c, userTripModel)
	} else {
		response.Abort500(c, "更新失败，请稍后尝试~")
	}
}

func (ctrl *UserTripsController) ModifyRemaining(c *gin.Context) {

	userTripModel := user_trip.GetById(c.Param("id"))
	if userTripModel.ID == 0 {
		response.Abort404(c)
		return
	}

	if ok := policies.CanModifyUserTrip(c, userTripModel); !ok {
		response.Abort403(c)
		return
	}

	request := requests.UserTripRemainingRequest{}
	if ok := requests.Validate(c, &request, requests.UserTripRemaining); !ok {
		return
	}

	if request.Type == "plus" {
		if userTripModel.Remaining >= userTripModel.Sites {
			response.Abort403(c, "剩余座位超过车辆最大座位数")
			return
		}
		userTripModel.Remaining = userTripModel.Remaining + 1
	} else {
		if userTripModel.Remaining <= 0 {
			response.Abort403(c, "已经没有剩余座位")
			return
		}
		userTripModel.Remaining = userTripModel.Remaining - 1
	}

	rowsAffected := userTripModel.Save()
	if rowsAffected > 0 {
		response.Data(c, userTripModel)
	} else {
		response.Abort500(c, "更新失败，请稍后尝试~")
	}
}

func (ctrl *UserTripsController) Delete(c *gin.Context) {

	userTripModel := user_trip.Get(c.Param("id"))
	if userTripModel.ID == 0 {
		response.Abort404(c)
		return
	}

	if ok := policies.CanModifyUserTrip(c, userTripModel); !ok {
		response.Abort403(c)
		return
	}

	rowsAffected := userTripModel.Delete()
	if rowsAffected > 0 {
		response.Success(c)
		return
	}

	response.Abort500(c, "删除失败，请稍后尝试~")
}

// 发车
func (ctrl *UserTripsController) Start(c *gin.Context) {
	userTripModel := user_trip.GetById(c.Param("id"))
	if userTripModel.ID == 0 {
		response.Abort404(c)
		return
	}

	if !policies.CanModifyUserTrip(c, userTripModel) {
		response.Abort403(c)
		return
	}

	// 已经发车，直接返回
	if userTripModel.Status == user_trip.SUCCESS {
		response.Data(c, userTripModel)
		return
	}

	// 取消状态，直接返回
	if userTripModel.Status == user_trip.CANCELLED {
		response.Abort403(c, "行程已被取消，无法发车")
		return
	}

	// 状态为未发车，需要将关联的乘客状态设置为已发车
	passengers, err := trip_passenger.GetPassengersByTripID(userTripModel.ID)
	if err != nil {
		response.Abort500(c, "获取乘客失败")
	}

	userTripModel.Status = user_trip.SUCCESS

	if rowsAffected := userTripModel.Save(); rowsAffected == 0 {
		response.Error(c, errors.New(("发车失败")))
		return
	}

	// 遍历乘客，通知所有待同意的乘客，并更新状态为已发车
	for _, passenger := range passengers {
		if passenger.Status == trip_passenger.PENDING {
			passenger.Status = trip_passenger.AUTO_CANCEL
			passenger.Save()
			// 发送通知
		}
	}

	response.Data(c, userTripModel)
}

// 取消
func (ctrl *UserTripsController) Cancel(c *gin.Context) {
	userTripModel := user_trip.GetById(c.Param("id"))
	if userTripModel.ID == 0 {
		response.Abort404(c)
		return
	}
	if !policies.CanModifyUserTrip(c, userTripModel) {
		response.Abort403(c)
		return
	}
	// 已经发车，直接返回
	if userTripModel.Status == user_trip.SUCCESS {
		response.Abort403(c, "已经发车，无法取消")
		return
	}
	// 取消状态，直接返回
	if userTripModel.Status == user_trip.CANCELLED {
		response.Data(c, userTripModel)
		return
	}
	// 状态为未发车，需要将关联的乘客状态设置为已取消
	passengers, err := trip_passenger.GetPassengersByTripID(userTripModel.ID)
	if err != nil {
		response.Abort500(c, "获取乘客失败")
	}
	userTripModel.Status = user_trip.CANCELLED
	userTripModel.Save()
	// 遍历乘客，通知所有乘客，并更新状态为已取消
	for _, passenger := range passengers {
		// 对于还没有确认的乘客，标记为自动取消
		if passenger.Status == trip_passenger.PENDING {
			passenger.Status = trip_passenger.AUTO_CANCEL
			passenger.Save()
		}

		// 对于已经确认的乘客，标记为被取消，还应该标记司机放鸽子人数，作为评判司机标准
		if passenger.Status == trip_passenger.CONFIRMED {
			passenger.Status = trip_passenger.CANCELLED
			passenger.Save()
		}
		// 发送通知

	}
	response.Data(c, userTripModel)
}
